﻿using RabbitMQ.Client.Events;
using RabbitMQ.Client;
using System.Text.Json;
using System.Text;
using System.Threading.Channels;

public class RabbitMQService
{
    private readonly IRabbitMQConnection _connection;

    public RabbitMQService(IRabbitMQConnection connection)
    {
        _connection = connection ?? throw new ArgumentNullException(nameof(connection));
    }

    public async Task SendAsync(string exchange, string routingKey, object message, bool mandatory = false, CancellationToken cancellationToken = default)
    {
        try
        {
            using var channel = await _connection.CreateChannel();
            var mesjson = JsonSerializer.Serialize(message);
            Console.WriteLine("发送消息：" + message.ToString());
            var body = Encoding.UTF8.GetBytes(mesjson);
            var properties = new RabbitMQ.Client.BasicProperties
            {
                Persistent = true, // 设置消息持久化
                //Expiration = "300"//设置TTL
            };
            await channel.BasicPublishAsync(exchange, routingKey, false, properties, body, cancellationToken);
        }
        catch (OperationCanceledException ex)
        {
            Console.WriteLine($"Operation was canceled: {ex.Message}");
            //throw; // Re-throw if you want to propagate the cancellation
        }
        catch (Exception ex)
        {
            Console.WriteLine($"An error occurred: {ex.Message}");
            //throw; // Re-throw if you want to propagate the error
        }
    }

    public async Task ReceiveAsync(string queueName, Func<IChannel, byte[], Task> callback, CancellationToken cancellationToken = default)
    {
        var channel = await _connection.CreateChannel();

        //// 1. 声明死信交换机（建议放在 Startup 或只声明一次）
        //await channel.ExchangeDeclareAsync("dlx.exchange", ExchangeType.Direct, durable: true);
        //await channel.QueueDeclareAsync("dlx.queue", durable: true, exclusive: false, autoDelete: false);
        //await channel.QueueBindAsync("dlx.queue", "dlx.exchange", "dlx.routing");

        //// 2. 设置业务队列的死信参数
        //var args = new Dictionary<string, object>
        //{
        //    { "x-dead-letter-exchange", "dlx.exchange" },
        //    { "x-dead-letter-routing-key", "dlx.routing" },
        //    {"x-message-ttl",300 }
        //};

        //await channel.QueueDeclareAsync(queue: queueName, durable: true, exclusive: false, autoDelete: false, arguments: args);

        var consumer = new AsyncEventingBasicConsumer(channel);
        consumer.ReceivedAsync += async (model, ea) =>
        {
            var body = ea.Body.ToArray();
            try
            {
                await channel.BasicNackAsync(ea.DeliveryTag, false, requeue: false);
                // 直接传递 model 和 body 给 callback，不需要转换
                //await callback(channel, body);
                //await channel.BasicAckAsync(ea.DeliveryTag, false);
            }
            catch
            {
                await channel.BasicNackAsync(ea.DeliveryTag, false, requeue: false);
            }
            //finally
            //{
            //    await channel.BasicAckAsync(ea.DeliveryTag, false, cancellationToken);
            //}
        };
        await channel.BasicConsumeAsync(queue: queueName, autoAck: false, consumer: consumer, cancellationToken: cancellationToken);
        // Prevent the method from returning immediately
        //这行代码防止 ReceiveAsync 方法立即退出，相当于“死等”直到取消。
        await Task.Delay(-1, cancellationToken);
    }
}